---
title: Component Style
description: How to create and theme custom components.
---

Writing component styles in a way that is easy to maintain over the life of a
growing and changing project is a challenging task.

To solve this, we came up with the idea of style configuration or `styleConfig`.
This is a consistent theming API that makes component styling easy to understand
and maintain.

## Base styles and Modifier styles

Most component style consists of **base or default styles** and **modifier
styles** that alter its size or visual style based on some properties or state.

Common modifier styles includes:

- **Size:** A component can have different sizes (e.g. small, medium, large)
- **Variant:** A component can have different visual styles (e.g. outline,
  solid, ghost)
- **Color scheme:** For a given variant, a component can have different color
  schemes (e.g. an outline button with a red color scheme)
- **Color mode:** A component can change its visual styles based on color mode
  (e.g. light or dark).

### Single part and multipart components

Most components we build today are either single part components (e.g. Button,
Badge) or multipart components (e.g. Tabs, Menu, Modal).

**A single part component** is a component that returns a single element. For
example, the `<Button>` component renders a `<button>` HTML element:

```jsx live=false
// This component renders only one element (<button>)
<Button>My button</Button>
```

**A multipart component** is a component that has multiple parts, and require
these parts to work correctly. This is commonly referred to as a composite
component.

For example, a `Tabs` component consists of `TabList`, `Tab`, `TabPanels`, and
`TabPanel`. Styling this component as a whole might require styling each
component part.

```jsx live=false
<Tabs>
  <TabList>
    <Tab>Tab 1</Tab>
    <Tab>Tab 2</Tab>
  </TabList>
  <TabPanels>
    <TabPanel>Tab 1</TabPanel>
    <TabPanel>Tab 2</TabPanel>
  </TabPanels>
</Tabs>
```

## Styling single part components

The basic API for styling a single part component is:

```jsx live=false
export default {
  // Styles for the base style
  baseStyle: {},
  // Styles for the size variations
  sizes: {},
  // Styles for the visual style variations
  variants: {},
  // The default `size` or `variant` values
  defaultProps: {},
}
```

Let's say we want to create a custom button component following the design spec
below.

<Img mt="10" mb="12" src="/button-spec.png" />

Here's a contrived implementation of the design:

```jsx live=false
const Button = {
  // The styles all button have in common
  baseStyle: {
    fontWeight: "bold",
    textTransform: "uppercase",
    borderRadius: "base", // <-- border radius is same for all variants and sizes
  },
  // Two sizes: sm and md
  sizes: {
    sm: {
      fontSize: "sm",
      px: 4, // <-- px is short for paddingLeft and paddingRight
      py: 3, // <-- py is short for paddingTop and paddingBottom
    },
    md: {
      fontSize: "md",
      px: 6, // <-- these values are tokens from the design system
      py: 4, // <-- these values are tokens from the design system
    },
  },
  // Two variants: outline and solid
  variants: {
    outline: {
      border: "2px solid",
      borderColor: "purple.500",
      color: "purple.500",
    },
    solid: {
      bg: "purple.500",
      color: "white",
    },
  },
  // The default size and variant values
  defaultProps: {
    size: "md",
    variant: "outline",
  },
}
```

Makes sense right? Now, let's update the theme to include this new component
style.

```jsx live=false
import { extendTheme } from "@chakra-ui/react"

const theme = extendTheme({
  components: {
    Button,
  },
})
```

**And that's it!** You can use your new Button along with its custom variants
throughout your app. But what if we want to create a custom component that's not
part of Chakra UI? Let's use the following design spec for a Card component:

<Img mt="10" mb="12" src="/card-spec.png" />

Here's a contrived implementation of the design:

```jsx live=false
const Card = {
  // The styles all Cards have in common
  baseStyle: {
    display: "flex",
    flexDirection: "column",
    background: "white",
    alignItems: "center",
    gap: 6,
  },
  // Two variants: rounded and smooth
  variants: {
    rounded: {
      padding: 8,
      borderRadius: "xl",
      boxShadow: "xl",
    },
    smooth: {
      padding: 6,
      borderRadius: "base",
      boxShadow: "md",
    },
  },
  // The default variant value
  defaultProps: {
    variant: "smooth",
  },
}
```

As with the Button component, we'll update the theme to include the new Card
component style.

```jsx live=false
import { extendTheme } from "@chakra-ui/react"

const theme = extendTheme({
  components: {
    Card,
  },
})
```

But in this case we'd have to **consume** these styles because the `Card`
component is not a built-in component in Chakra UI.

### Consuming style config

Since the new Card component is **not** part of Chakra UI we need to create a
new React component and consume the style we just created. We can do that using
`useStyleConfig` hook.

### useStyleConfig API

```jsx live=false
const styles = useStyleConfig(themeKey, props)
```

#### Parameters

- `themeKey`: the key in `theme.components` that points to the desired
  styleConfig.
- `props`: the options object used to compute the component styles. It typically
  consists of the `size`, `variant`, and `colorScheme`

#### Return Value

The computed styles for the component based on `props` passed. If no `props` is
passed, the `defaultProps` defined in the style config will be used.

```jsx live=false
import { Box, useStyleConfig } from "@chakra-ui/react"

function Card(props) {
  const { variant, children, ...rest } = props

  const styles = useStyleConfig("Card", { variant })

  // Pass the computed styles into the `__css` prop
  return <Box __css={styles} {...rest} />
}
```

> Please note that we are passing the styles to the prop `__css`. It has the
> same API as [the `sx` prop](/docs/features/the-sx-prop), but has a lower style
> priority. This means you can override the style properties with chakra style
> props.

And lastly - the fun part - let's use our custom Card component anywhere in our
app:

```jsx live=false
// 1. Using the default props defined in style config
function Usage() {
  return (
    <Card>
      <Image
        src="https://chakra-ui.com/eric.jpg"
        rounded="full"
        w={32}
        h={32}
        boxShadow="md"
      />
      <Heading mt={6} maxW={60} size="lg" textAlign="center" color="gray.700">
        Welcome back, Eric
      </Heading>
      <Text mt={6} mb={6} size="sm" color="blackAlpha.500">
        Use your fingerprint to continue.
      </Text>
      <Image src="/fingerprint.png" w={32} h={32} />
    </Card>
  )
}

// 2. Overriding the default
function Usage() {
  return (
    <Card variant="smooth">
      <Image
        src="https://chakra-ui.com/eric.jpg"
        rounded="full"
        w={32}
        h={32}
        boxShadow="md"
      />
      <Heading mt={6} maxW={60} size="lg" textAlign="center" color="gray.700">
        Welcome back, Eric
      </Heading>
      <Text mt={6} mb={6} size="sm" color="blackAlpha.500">
        Use your fingerprint to continue.
      </Text>
      <Image src="/fingerprint.png" w={32} h={32} />
    </Card>
  )
}
```

## Styling multipart components

This is very similar to styling single part components with a few differences
you need to be aware of.

- Given that multipart refers to a component with multiple parts, you'll need to
  define the parts in a `part` key in the style config.
- You'll need to provide styles for each `part`, `baseStyle`, `sizes`, and
  `variants`.

> **Pro tip 💡**:
> If you're looking for a list of parts of a multipart component you can check it by clicking on the
> **"View theme source"** button at the top of the documentation page for that
> certain component. Check out [this](https://chakra-ui.com/docs/overlay/modal) example.

Here's what the style config for multipart components looks like:

```jsx live=false
export default {
  // The parts of the component
  parts: [],
  // The base styles for each part
  baseStyle: {},
  // The size styles for each part
  sizes: {},
  // The variant styles for each part
  variants: {},
  // The default `size` or `variant` values
  defaultProps: {},
}
```

For example, here's what the style configurations for a custom menu component
looks like:

```jsx live=false
const Menu = {
  parts: ["menu", "item"],
  baseStyle: {
    menu: {
      boxShadow: "lg",
      rounded: "lg",
      flexDirection: "column",
      py: "2",
    },
    item: {
      fontWeight: "medium",
      lineHeight: "normal",
      color: "gray.600",
    },
  },
  sizes: {
    sm: {
      item: {
        fontSize: "0.75rem",
        px: 2,
        py: 1,
      },
    },
    md: {
      item: {
        fontSize: "0.875rem",
        px: 3,
        py: 2,
      },
    },
  },
  defaultProps: {
    size: "md",
  },
}
```

Next, we'll update the theme object to included this new component style.

```jsx live=false
import { extendTheme } from "@chakra-ui/react"

const theme = extendTheme({
  components: {
    Menu,
  },
})
```

### Consuming multipart style config

Now that the style config is hooked into the theme, we can consume within any
component using `useMultiStyleConfig` hook.

We can also mount the computed styles on a specialized context provider called
`StylesProvider`. These styles will now be available to other sub-components. To
read from the context, use the `useStyles` hook.

### useMultiStyleConfig API

```jsx live=false
const styles = useMultiStyleConfig(themeKey, props)
```

#### Parameters

- `themeKey`: the key in `theme.components` that points to the desired
  styleConfig.
- `props`: an option of the options for computing the final styles. It typically
  consists of the `size`, `variant`, and `colorScheme`.

#### Return Values

The computed styles for each component part based on `size`, or `variant`. If
none of these were passed, the `defaultProps` defined in the styleConfig will be
used.

```jsx live=false
// 1. Import the components and hook
import {
  StylesProvider,
  useMultiStyleConfig,
  useStyles,
} from "@chakra-ui/react"

function Menu(props) {
  const { size, variant, children, ...rest } = props

  // 2. Consume the `useMultiStyleConfig` hook
  const styles = useMultiStyleConfig("Menu", { size, variant })

  return (
    <Flex __css={styles.menu} {...rest}>
      {/* 3. Mount the computed styles on `StylesProvider` */}
      <StylesProvider value={styles}>{children}</StylesProvider>
    </Flex>
  )
}

function MenuItem(props) {
  // 4. Read computed `item` styles from styles provider
  const styles = useStyles()
  return <Box as="button" __css={styles.item} {...props} />
}
```

That's it! We can use our newly created multipart component in our application:

```jsx live=false
// 1. Using the default props defined in style config
function Usage() {
  return (
    <Menu>
      <MenuItem>Awesome</MenuItem>
      <MenuItem>Sauce</MenuItem>
    </Menu>
  )
}

// 2. Overriding the default
function Usage() {
  return (
    <Menu size="sm">
      <MenuItem>Awesome</MenuItem>
      <MenuItem>Sauce</MenuItem>
    </Menu>
  )
}
```
